﻿using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Reflection;
using SimpleCore;
using SimpleCore.Tool;
using UnityEditor;
using UnityEngine;

namespace SimpleEditor.ExcelTool
{
    public class ConfigDataFileCreator
    {
        [MenuItem("Simple Tools/Config Data/Create Data Files")]
        static void CreateDatas()
        {
            _assembly = typeof(DataSerializeHelper).Assembly;
            
            var excelFiles = GetExcelFiles();

            for (int i = 0; i < excelFiles.Length; i++)
            {
                CreateData(excelFiles[i]);
            }
            
            Debug.Log("Create Finished !!!");
        }

        static string[] GetExcelFiles()
        {
            string path = $"{Application.dataPath.Replace("Assets", "")}/Excel";
            var files = Directory.GetFiles(path).Where(a => a.EndsWith(".xls") || a.EndsWith(".xlsx")).ToArray();

            return files;
        }

        static void CreateData(string excelPath)
        {
            string excelFileName = Path.GetFileNameWithoutExtension(excelPath);

            var dataType = typeof(DataSerializeHelper).Assembly.GetType($"{excelFileName}ConfigData");//Type.GetType($"{excelFileName}ConfigData");
            if (dataType == null)
            {
                Debug.LogError($"Dont Find This Type {excelFileName}ConfigData");
                return;
            }

            DataSet dataSet = ExcelReaderHelper.Read(excelPath);
            var attrInfoMap = GetAttrInfoMap(dataSet);
            
            List<object> datas = new List<object>();
            var table = dataSet.Tables[0];
            for (int i = 4; i < table.Rows.Count; i++)
            {
                var data = _assembly.CreateInstance($"{excelFileName}ConfigData", false);
                foreach (var a in attrInfoMap)
                {
                    FillCell(data, dataType, a.Value, table.Rows[i][a.Key].ToString());
                }
                datas.Add(data);
            }
            
            DataSerializeHelper helper = new DataSerializeHelper();
            helper.datas = datas;

            string dataFilePath = $"{Application.dataPath}{ConfigDataPath}{excelFileName}.txt";
            SerializeTool.Serialize(dataFilePath, helper);
        }

        static void FillCell(object data, Type dataType, ExcelAttrInfo attrInfo, string value)
        {
            FieldInfo field;
            if (attrInfo.attrName.ToLower() == "id")
            {
                field = dataType.GetField("id");
            }
            else
            {
                field = dataType.GetField(attrInfo.attrName);
            }
            
            field.SetValue(data, HandleCellValue(attrInfo, value));
        }

        static object HandleCellValue(ExcelAttrInfo info, string value)
        {
            value = string.IsNullOrEmpty(value) ? info.defaultValue : value;
            switch (info.attrType.ToUpper())
            {
                case "INT":
                    return ConvertTool.StringToInt(value);
                case "FLOAT":
                    return ConvertTool.StringToFloat(value);
                case "STRING":
                    return value;
                case "BOOL":
                    return ConvertTool.StringToBool(value);
                case "LIST<INT>":
                    return ConvertTool.StringToListInt(value);
                case "LIST<FLOAT>":
                    return ConvertTool.StringToListFloat(value);
                case "LIST<STRING>":
                    return ConvertTool.StringToListString(value);
                case "LIST<BOOL>":
                    return ConvertTool.StringToListBool(value);
                default:
                    Debug.LogError($"other type, need extend !!!  {info.attrType.ToUpper()}");
                    return null;
            }
        }

        static Dictionary<int, ExcelAttrInfo> GetAttrInfoMap(DataSet dataSet)
        {
            var table = dataSet.Tables[0];
            Dictionary<int, ExcelAttrInfo> attrInfoMap = new Dictionary<int, ExcelAttrInfo>();
            for (int i = 0; i < table.Rows[1].ItemArray.Length; i++)
            {
                var attrInfo = new ExcelAttrInfo();
                attrInfo.attrName = table.Rows[1][i].ToString();
                attrInfo.attrType = table.Rows[2][i].ToString();
                attrInfo.defaultValue = table.Rows[3][i].ToString();
                if (attrInfo.IsRight())
                {
                    attrInfoMap.Add(i, attrInfo);
                }
            }

            return attrInfoMap;
        }

        private static Assembly _assembly;

        private const string ConfigDataPath = "/Resources/ConfigData/";
    }


    class ExcelAttrInfo
    {
        public string attrName;
        public string attrType;
        public string defaultValue;

        public bool IsRight()
        {
            return !string.IsNullOrEmpty(attrName) 
                   && !string.IsNullOrEmpty(attrType);
        }
    }
}
